module neo.tetris.model {
	/**
	 *
	 * @author 
	 *
	 */
	export class App extends neo.typescript.model.Bean {
        private _synchronizeTime: number;
        public set synchronizeTime(value:number) {
            this._synchronizeTime = value;
            this._synchronizeLocalTime = egret.getTimer();
        }
        
        private _synchronizeLocalTime;
        public get serverTime():number {
            return this._synchronizeTime + egret.getTimer() - this._synchronizeLocalTime;
        }
    	
        public static LOGINED: string = "LOGINED";
	    public get logined():AppUser {
            return this.getProperty(App.LOGINED);
	    }
	    public set logined(value:AppUser) {
            this.setProperty(App.LOGINED,value);
	    }
	    
        public static BATTLE: string = "BATTLE";
        public get battle():BattleModel {
            return this.getProperty(App.BATTLE);
        }
        public set battle(value:BattleModel) {
            this.setProperty(App.BATTLE,value);
        }
	}
	
	export class AppUser extends neo.typescript.model.Bean {
        public static UUID: string = "UUID";
        public get uuid():string {
            return this.getProperty(AppUser.UUID);
        }
        public set uuid(value:string) {
            this.setProperty(AppUser.UUID,value);
        }

        public static NAME: string = "NAME";
        public get name(): string {
            return this.getProperty(AppUser.NAME);
        }
        public set name(value:string) {
            this.setProperty(AppUser.NAME,value);
        }
        
        public static ICON: string = "ICON";
        public get icon():string {
            return this.getProperty(AppUser.ICON);
        }
        public set icon(value:string) {
            this.setProperty(AppUser.ICON,value);
        }
        /**
        public static BATTLE_PLAYER: string = "BATTLE_PLAYER";
        public get battlePlayer():BattlePlayerModel {
            return this.getProperty(AppUser.BATTLE_PLAYER);
        }
        public set battlePlayer(value:BattlePlayerModel) {
            this.setProperty(AppUser.BATTLE_PLAYER,value);
        }
        */
	}
	
	export class BattleModel extends neo.typescript.model.Bean {
        public static START_TIME: string = "START_TIME";
        public get startTime():number {
            return this.getProperty(BattleModel.START_TIME);
        }
        public set startTime(value:number) {
            this.setProperty(BattleModel.START_TIME,value);
        }

        public static PLAYERS:string = "PLAYERS";
        public get players():BattlePlayerModel[] {
            return this.getProperty(BattleModel.PLAYERS);
        }
        public set players(value: BattlePlayerModel[]) {
            this.setProperty(BattleModel.PLAYERS,value);
        }
        
        public static WINNER: string = "winner";
        public get winner():BattlePlayerModel {
            return this.getProperty(BattleModel.WINNER);
        }
        public set winner(value:BattlePlayerModel) {
            this.setProperty(BattleModel.WINNER,value);
        }
        
        public constructor() {
            super();
            
            this.players = [];
        }
	}
	
	export class BattlePlayerModel extends neo.typescript.model.Bean {
        public battle: BattleModel;
        
        public id: number;
        
        public userUUid: string;
        
        public name: string;

        public headIcon: string;
        
        public tetris: TetrisModel;
        
        public piece: ShapeModel;
        
        public static ADD_DIFFICULT_TIME: string = "ADD_DIFFICULT_TIME";
        public get addDifficultTime():number {
            return this.getProperty(BattlePlayerModel.ADD_DIFFICULT_TIME);
        }
        public set addDifficultTime(value:number) {
            this.setProperty(BattlePlayerModel.ADD_DIFFICULT_TIME,value);
        }
        
        public constructor(battle:BattleModel) {
            super();
            
            this.battle = battle;
            this.tetris = new TetrisModel();
        }
	}
	
    export class TetrisModel extends neo.typescript.model.Bean {
        public static getShape(id:number):ShapeModel {
            switch(id) {
                case 1:
                    return ZShape;
                    break;
                case 2:
                    return SShape;
                    break;
                case 3:
                    return LineShape;
                    break;
                case 4:
                    return TShape;
                case 5:
                    return SquareShape;
                case 6:
                    return LShape;
                case 7:
                    return MirroredLShape;

            }
        }

        public static get column(): number {
            return 10;
        }

        public static get row(): number {
            return 20;
        }
        
        public numLinesRemoved: number = 0;

        public curPiece: neo.tetris.model.ShapeModel;

        public static SHAPES: string = "SHAPES";
        public get shapes(): neo.tetris.model.ShapeModel[] {
            return this.getProperty(TetrisModel.SHAPES);
        }
        public set shapes(value:neo.tetris.model.ShapeModel[]) {
            this.setProperty(TetrisModel.SHAPES,value);
        }
        
        public constructor() {
            super();
            
            this.shapes = [];
        }
        
        public shapeAt(col:number, row:number):ShapeModel {
            return this.shapes[col + TetrisModel.column * row];
        }
    }

	export class ShapeModel {
    	public catalog: number;
    	
        public coords: number[][];
    	
        public constructor(coordsTable:number[][], catalog:number) {
            this.coords = [];
            for(var i: number = 0;i < 4;i++) {
                this.coords[i] = [];
                for(var j: number = 0;j < 2;++j) {
                    this.coords[i][j] = coordsTable[i][j];
                }
            }
            this.catalog = catalog;
		}
		
        private setX(index:number,x:number):void {
            this.coords[index][0] = x;
        }
    
    	private setY(index:number, y:number):void {
            this.coords[index][1] = y;
        }
    
    	public getX(index:number):number {
            return this.coords[index][0];
        }
    
    	public getY(index:number):number {
            return this.coords[index][1];
        }
    
    	public minX():number {
            var m:number = this.coords[0][0];
            for(var i:number = 0;i < 4; i++) {
                m = Math.min(m,this.coords[i][0]);
            }
            return m;
        }
    
    	public minY():number {
            var m:number = this.coords[0][1];
            for(var i:number = 0;i < 4; i++) {
                m = Math.min(m,this.coords[i][1]);
            }
            return m;
        }
    
    	public rotateLeft():ShapeModel {
//            if(this.pieceShape == Tetrominoes.SquareShape)
//                return this;

            var result: ShapeModel = new ShapeModel(this.coords, this.catalog);
            for(var i:number = 0;i < 4; ++i) {
                result.setX(i,this.getY(i));
                result.setY(i,-this.getX(i));
            }
            return result;
        }

    	public rotateRight():ShapeModel {
//            if(this.pieceShape == Tetrominoes.SquareShape)
//                return this;

            var result:ShapeModel = new ShapeModel(this.coords, this.catalog);
            for(var i:number = 0;i < 4; ++i) {
                result.setX(i,-this.getY(i));
                result.setY(i,this.getX(i));
            }
            return result;
        }
	}

    export const ZShape: ShapeModel = new ShapeModel([[0,-1],[0,0],[-1,0],[-1,1]], 1);
    export const SShape: ShapeModel = new ShapeModel([[0,-1],[0,0],[1,0],[1,1]], 2);
    export const LineShape: ShapeModel = new ShapeModel([[0,-1],[0,0],[0,1],[0,2]], 3);
    export const TShape: ShapeModel = new ShapeModel([[-1,0],[0,0],[1,0],[0,1]], 4);
    export const SquareShape: ShapeModel = new ShapeModel([[0,0],[1,0],[0,1],[1,1]], 5);
    export const LShape: ShapeModel = new ShapeModel([[-1,-1],[0,-1],[0,0],[0,1]], 6);
    export const MirroredLShape: ShapeModel = new ShapeModel([[1,-1],[0,-1],[0,0],[0,1]], 7);
    export const ALL: ShapeModel[] = [ZShape, SShape, LineShape, TShape, SquareShape, LShape, MirroredLShape];
    
    export const appInstance: App = new App();
}
